//! `std::ffi` 模块的测试用例
//!
//! 本文件包含对 `std::ffi` 中与外部函数接口 (FFI) 相关的类型的测试，
//! 主要包括 `CString`, `CStr`, `OsString`, 和 `OsStr`。

#[cfg(test)]
mod tests {
    use std::ffi::{CStr, CString, OsStr, OsString};
    use std::os::raw::c_char;

    // --- CString 和 CStr 的测试 ---

    /// 测试 `CString` 的创建和转换
    #[test]
    fn test_cstring_creation() {
        // 从 Rust 字符串创建 CString
        let c_string = CString::new("hello").unwrap();

        // `as_bytes_with_nul` 返回一个包含 null 终止符的字节切片
        assert_eq!(c_string.as_bytes_with_nul(), b"hello\0");
    }

    /// 测试 `CString` 创建失败的情况（包含内部 null 字符）
    #[test]
    fn test_cstring_creation_with_nul() {
        let result = CString::new("he\0llo");
        assert!(result.is_err());
    }

    /// 测试 `CStr` 的使用
    #[test]
    fn test_cstr_from_bytes() {
        // 模拟一个 C 字符串（以 null 结尾）
        let c_string_literal = b"world\0";

        // 从字节切片创建 CStr
        let c_str = CStr::from_bytes_with_nul(c_string_literal).unwrap();

        // 转换为 Rust 的 &str
        assert_eq!(c_str.to_str().unwrap(), "world");
    }

    /// 测试 `CString` 和 `CStr` 的相互转换
    #[test]
    fn test_cstring_to_cstr() {
        let c_string = CString::new("test").unwrap();
        let c_str: &CStr = c_string.as_c_str();

        assert_eq!(c_str.to_string_lossy(), "test");
    }

    /// 模拟 FFI 调用场景
    #[test]
    fn test_ffi_simulation() {
        let rust_str = "ffi_simulation";
        let c_string = CString::new(rust_str).unwrap();

        // 模拟将 CString 指针传递给 C 函数
        let ptr: *const c_char = c_string.as_ptr();

        // 模拟在 C 函数中接收指针并转换回 CStr
        let received_c_str = unsafe { CStr::from_ptr(ptr) };

        assert_eq!(received_c_str.to_str().unwrap(), rust_str);
    }

    // --- OsString 和 OsStr 的测试 ---

    /// 测试 `OsString` 的创建和转换
    #[test]
    fn test_osstring_creation() {
        // OsString 可以包含非 UTF-8 数据，更适合表示操作系统原生字符串（如文件路径）
        let os_string = OsString::from("path/to/file");

        // 转换为 OsStr
        let os_str: &OsStr = os_string.as_os_str();

        assert_eq!(os_str.to_string_lossy(), "path/to/file");
    }

    /// 在 Unix 系统上测试包含无效 UTF-8 序列的 OsString
    #[test]
    #[cfg(unix)]
    fn test_osstring_with_invalid_utf8_on_unix() {
        use std::os::unix::ffi::OsStrExt;

        // 包含无效 UTF-8 字节序列
        let bytes = b"invalid-\xff-utf8";
        let os_str = OsStr::from_bytes(bytes);

        // `to_string_lossy` 会替换无效字符
        assert_eq!(os_str.to_string_lossy(), "invalid--utf8");

        // 可以安全地转换回原始字节
        assert_eq!(os_str.as_bytes(), bytes);
    }

    /// 在 Windows 系统上测试宽字符串（UTF-16）的转换
    #[test]
    #[cfg(windows)]
    fn test_osstring_with_wide_str_on_windows() {
        use std::os::windows::ffi::{OsStrExt, OsStringExt};

        let original_str = "你好, world!";
        let wide_chars: Vec<u16> = original_str.encode_utf16().collect();

        // 从 UTF-16 创建 OsString
        let os_string = OsString::from_wide(&wide_chars);

        // 转换回 UTF-16
        let collected_wide: Vec<u16> = os_string.encode_wide().collect();
        assert_eq!(wide_chars, collected_wide);

        // 转换为 Rust 字符串
        assert_eq!(os_string.to_string_lossy(), original_str);
    }
}
